﻿using Innoapps.FileTransfer.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Innoapps.FileTransfer.Adapters.Receive
{
    public class FTP : Base
    {

        #region Enumerations
        public enum FtpRepresentations
        {
            Binary = 1,
            ASCII = 2
        }

        #endregion

        #region Properties

        [XmlAttribute("uri")]
        public override string uri
        {
            get
            {
                return "ftp://"
                    + UserName
                    + (UserName != "" && Password != "" ? ":" : "")
                    + (UserName != "" || Password != "" ? "@" : "")
                    + Path.Combine(Path.Combine(Server, FolderPath), FileName);
            }
            set
            {
                Uri u = new Uri(value);

                UserName = u.UserInfo != "" ? u.UserInfo.Split(':')[0] : UserName;
                Password = u.UserInfo != "" && u.UserInfo.Contains(":") ? u.UserInfo.Split(':')[1] : Password;
                Server = u.Host;
                Port = u.Port;
                if (u.IsFile)
                    FileName = Path.GetFileName(u.LocalPath);

                FolderPath = Path.GetDirectoryName(u.LocalPath);

            }
        }


        [XmlAttribute("Password")]
        public string Password { get; set; }

        [XmlAttribute("Port")]
        public int Port { get; set; }

        [XmlAttribute("Representation")]
        public FtpRepresentations Representation { get; set; }

        [XmlAttribute("Server")]
        public string Server { get; set; }

        [XmlAttribute("UserName")]
        public string UserName { get; set; }

        [XmlAttribute("DeleteAfterTransfer")]
        public bool DeleteAfterTransfer { get; set; }

        [XmlAttribute("FolderPath")]
        public string FolderPath { get; set; }
        [XmlAttribute("FileName")]
        public string FileName { get; set; }

        [XmlAttribute("TemporaryFolder")]
        public string TemporaryFolder { get; set; }

        #endregion

        #region Methods

        public override void Receive()
        {
            try
            {

                Stream stream;
                string uri = this.uri;
                FtpWebRequest request;
                FtpWebResponse response;
                NetworkCredential credential;

                if(UserName != "")
                {
                    credential = new NetworkCredential(UserName, Password);
                } else
                {
                    credential = CredentialCache.DefaultNetworkCredentials;
                }

                if (TemporaryFolder != "")
                {

                    request = (FtpWebRequest)WebRequest.Create(uri);
                    request.Method = WebRequestMethods.Ftp.Rename;

                    request.Credentials = credential;
                    request.RenameTo = Path.Combine(TemporaryFolder, FileName);

                    response = (FtpWebResponse)request.GetResponse();

                    // Handle web response error codes
                    if ((int)response.StatusCode < 200 || (int)response.StatusCode > 299)
                    {
                        Fail(response.StatusDescription);
                        return;
                    }

                    uri = Path.Combine(TemporaryFolder, FileName);

                }

                request = (FtpWebRequest)WebRequest.Create(uri);
                request.Method = WebRequestMethods.Ftp.DownloadFile;
                request.Credentials = credential;
                request.UseBinary = (Representation == FtpRepresentations.Binary);

                response = (FtpWebResponse)request.GetResponse();

                // Handle web response error codes
                if((int)response.StatusCode < 200 || (int)response.StatusCode > 299)
                {
                    Fail(response.StatusDescription);
                    return;
                }


                stream = response.GetResponseStream();

                transfer.Stream = stream;
                Pass();
            }
            catch (Exception e)
            {
                Fail(e.Message);
            }
        }

        public override void Delete()
        {
            try
            {

                string uri = this.uri;
                FtpWebRequest request;
                FtpWebResponse response;
                NetworkCredential credential;

                if (UserName != "")
                {
                    credential = new NetworkCredential(UserName, Password);
                }
                else
                {
                    credential = CredentialCache.DefaultNetworkCredentials;
                }

                if (TemporaryFolder != "")
                {

                    uri = Path.Combine(TemporaryFolder, FileName);

                }

                request = (FtpWebRequest)WebRequest.Create(uri);
                request.Method = WebRequestMethods.Ftp.DeleteFile;
                request.Credentials = credential;

                response = (FtpWebResponse)request.GetResponse();

                //TODO: Handle web response error codes


                Pass();
            }
            catch (Exception e)
            {
                Fail(e.Message);
            }
        }

        #endregion

    }
}
